package com.base.cn.platform.os.service.order.order;

import com.base.cn.platform.os.common.mybatis.BaseBiz;
import com.base.cn.platform.os.common.mybatis.Pagination;
import com.base.cn.platform.os.common.utils.DataUtil;
import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.order.OrderStatus;
import com.base.cn.platform.os.common.utils.order.ShopType;
import com.base.cn.platform.os.dao.order.order.OrderDetailsDao;
import com.base.cn.platform.os.entity.order.PayCallbackEntity;
import com.base.cn.platform.os.entity.order.count.OrderSubjectNum;
import com.base.cn.platform.os.entity.order.order.Order;
import com.base.cn.platform.os.entity.order.order.OrderBook;
import com.base.cn.platform.os.entity.order.order.OrderDetails;
import com.base.cn.platform.os.entity.order.order.OrderDetailsCondition;
import com.base.cn.platform.os.entity.order.shop.ShopData;
import com.base.cn.platform.os.entity.statistics.trade.TradePayOrderNum;
import com.base.cn.platform.os.entity.user.user.CusUser;
import com.base.cn.platform.os.entity.user.user.UserCondition;
import com.base.cn.platform.os.service.order.callback.OrderDetailsStatusHandle;
import com.base.cn.platform.os.service.order.check.CreateOrderDataFrom;
import com.base.cn.platform.os.service.order.init.ShopDataInit;
import com.base.cn.platform.os.service.user.user.CusUserBiz;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.joining;

/**
 * 订单流水记录BIz
 *
 * @author s.li
 * @create 2018-05-08-11:35
 */
@Service
public class OrderDetailsBiz extends BaseBiz<OrderDetails,OrderDetailsDao> {

    @Autowired
    private CusUserBiz cusUserBiz;
    @Autowired
    private OrderBookBiz orderBookBiz;
    @Autowired
    private OrderDetailsStatusHandle orderDetailsStatusHandle;
    @Autowired
    private OrderDetailsDao orderDetailsDao;
    @Autowired
    private OrderBiz orderBiz;
    @Autowired
    private ShopDataInit shopDataInit;

    /**
     * 修改订单流水状态
     * @param details 流水对象
     */
    @Transactional(rollbackFor = IllegalArgumentException.class )
    public void updateOrderDetailsStatus(OrderDetails details,BigDecimal sysUserId) throws Exception{
        //延期流水时不修改数据
        if(!details.getDetailStatus().equals(OrderStatus.COURSE)){
            this.updateById(details,null);
        }

        //关闭课程、会员流水
        if((details.getShopType().equals(ShopType.ORDER_SHOP_COURSE) || details.getShopType().equals(ShopType.ORDER_SHOP_MEMBER))
                && details.getDetailStatus().equals(OrderStatus.CLOSE)){
            orderDetailsStatusHandle.closeOrderDetails(details);
        }
        //退款
        if(details.getDetailStatus().equals(OrderStatus.REFUND)){
            orderDetailsStatusHandle.refundOrderDetails(details,sysUserId);
        }

    }

    /**
     * 创建充值流水数据
     * @param order 订单对象
     * @param payCallbackEntity 支付参数
     * @param setUserData 是否设置用户数据
     * @param setShopData 是否设置商品数据
     * @return
     */
    public OrderDetails saveAccountOrderDetails(Order order, PayCallbackEntity payCallbackEntity, boolean setUserData, boolean setShopData){
        //创建订单流水
        OrderDetails orderDetails = new OrderDetails();
        orderDetails.setOrderId(order.getId());
        orderDetails.setOrderNo(order.getOrderNo());
        orderDetails.setPayType(order.getPayType());
        orderDetails.setUserId(order.getUserId());
        orderDetails.setShopType(ShopType.ORDER_SHOP_ACCOUNT);
        orderDetails.setShopName("账户充值");
        orderDetails.setBuyNum(1);
        orderDetails.setPayTime(order.getPayTime());
        orderDetails.setDetailStatus(order.getOrderStatus());
        orderDetails.setPrice(payCallbackEntity.getPrice());
        orderDetails.setRealPrice(payCallbackEntity.getPrice());
        this.save(orderDetails);
        List<OrderDetails> orderDetailsList = new ArrayList<>();
        orderDetailsList.add(orderDetails);
        this.setOrderDetailsExData(orderDetailsList,setUserData,setShopData,false);
        return orderDetailsList.get(0);
    }

    /**
     * 通过订单ID串，查询流水集合，并通过订单ID分组
     * @param orderIds 订单ID串
     * @param setUserData 设置用户数据
     * @param setShopData 设置商品数据
     * @param setOrderBook 是否设置图书订单扩展数据
     * @return Map<BigDecimal,List<OrderDetails>>
     */
    public Map<BigDecimal,List<OrderDetails>> findOrderDetailsMapByOrderIds(String orderIds,boolean setUserData,boolean setShopData,boolean setOrderBook){
        List<OrderDetails> orderDetailsList = this.findOrderDetailsListByOrderIds(orderIds,setUserData,setShopData,setOrderBook);
        if(ObjectUtils.isNotEmpty(orderDetailsList)){
            return orderDetailsList.stream().collect(Collectors.groupingBy(e->e.getOrderId()));
        }
        return null;
    }

    /**
     * 通过订单ID串，查询流水列表
     * @param id
     * @param setUserData 设置用户数据
     * @param setShopData 设置商品数据
     * @param setOrderBook 是否设置图书订单扩展数据
     * @return OrderDetails
     */
    public OrderDetails findOrderDetailsById(BigDecimal id,boolean setUserData,boolean setShopData,boolean setOrderBook){
        OrderDetailsCondition condition = new OrderDetailsCondition();
        condition.setId(id);
        List<OrderDetails> orderDetailsList = this.findOrderDetailsList(condition,setUserData,setShopData,setOrderBook);
        if(ObjectUtils.isNotEmpty(orderDetailsList)){
            return orderDetailsList.get(0);
        }
        return null;
    }

    /**
     * 通过订单ID串，查询流水列表
     * @param orderIds 订单ID串
     * @param setUserData 设置用户数据
     * @param setShopData 设置商品数据
     * @param setOrderBook 是否设置图书订单扩展数据
     * @return List<OrderDetails>
     */
    public List<OrderDetails> findOrderDetailsListByOrderIds(String orderIds,boolean setUserData,boolean setShopData,boolean setOrderBook){
        OrderDetailsCondition condition = new OrderDetailsCondition();
        condition.setOrderIds(orderIds);
        return this.findOrderDetailsList(condition,setUserData,setShopData,setOrderBook);
    }

    /**
     * 多条件查询条件流水列表
     * @param condition 查询条件
     * @param setUserData 是否设置用户数据，
     * @param setShopData 是否设置商品数据
     * @param setOrderBook 是否设置图书订单扩展数据
     * @return List<OrderDetails>
     */
    public List<OrderDetails> findOrderDetailsList(OrderDetailsCondition condition,boolean setUserData,boolean setShopData,boolean setOrderBook){
        List<OrderDetails> orderDetailsList = this.find(this.getWhereSql(condition),null,null);
        this.setOrderDetailsExData(orderDetailsList,setUserData,setShopData,setOrderBook);
        return orderDetailsList;
    }

    /**
     * 获取购买课程的用户IDS
     * @param courseIds
     * @return
     */
    public Map<BigDecimal,String> queryBuyCourseUserCount(String courseIds){
        if (StringUtils.isNotEmpty(courseIds)){
            courseIds=StringUtils.subHeadTailString(courseIds,",");
            List<OrderDetails> orderDetails =this.find(" shopType='COURSE' and shopId in("+courseIds+") and detailStatus='SUCCESS'",null,null);
            Map<BigDecimal, String> group = orderDetails.stream() .collect(Collectors.groupingBy(OrderDetails::getShopId, Collectors.mapping((v) -> v.getUserId().toString(),
                    Collectors.collectingAndThen(Collectors.toList(), (v) -> v.stream().distinct().collect(joining(","))))));
            return group;
        }
        return null;
    }

    /**
     * 分页查询订单流水数据
     * @param condition 查询条件
     * @param setUserData 是否设置用户数据
     * @param setShopData 是否设置商品数据
     * @param setOrderBook 是否设置图书订单扩展数据
     * @return PageInfo<OrderDetails>
     */
    public PageInfo<OrderDetails> findOrderDetailsPage(OrderDetailsCondition condition,
                                                       Pagination page, boolean setUserData, boolean setShopData,boolean setOrderBook){
        condition.setUserIds(this.getUsrIds(condition.getKeyword()));
        PageInfo<OrderDetails> orderDetailsPageInfo = this.findPage(this.getWhereSql(condition),page,null);
        this.setOrderDetailsExData(orderDetailsPageInfo.getList(),setUserData,setShopData,setOrderBook);
        return orderDetailsPageInfo;
    }

    /**
     * 统计专业的销售额度的对比数据
     * @return List<OrderSubjectNum>
     */
    public List<OrderSubjectNum> queryOrderSubjectPriceCountNum(){
        return orderDetailsDao.queryOrderSubjectPriceCountNum(OrderDetails.class);
    }
    //=================================

    /**
     * 获取Keyword的条件SQL
     * @param keyword
     * @param userIds
     * @return
     */
    public String getKeywordSql(String keyword,String userIds){
        if(StringUtils.isNotEmpty(keyword)){
            if(StringUtils.isEmpty(userIds)){
                return " and orderNo like '"+keyword.trim()+"'";
            }else{
                return " and (orderNo like '"+keyword.trim()+"' or userId in ("+userIds+"))";
            }
        }
        return "";
    }
    /**
     * 获取用户ID串
     * @param keyword 查询条件
     * @return 用户ID串
     */
    public String getUsrIds(String keyword){
        if(StringUtils.isNotEmpty(keyword)){
            UserCondition userCondition = new UserCondition();
            userCondition.setKeyWord(keyword);
            List<CusUser> userList = cusUserBiz.queryUserList(userCondition,null,null,false,false,false,false,false,false,false);
            if(ObjectUtils.isNotEmpty(userList)){
                String userIds = userList.stream().map(e->e.getId().toString()).collect(Collectors.joining(","));
                return userIds;
            }
        }
        return null;
    }

    /**
     * 设置流水的扩展数据
     * @param orderDetailsList 流水数据列表
     * @param setUserData 是否设置用户数据
     * @param setShopData  是否设置商品数据
     * @param setOrderBook 是否设置图书订单扩展数据
     * @return List<OrderDetails>
     */
    private List<OrderDetails> setOrderDetailsExData(List<OrderDetails> orderDetailsList,boolean setUserData,
                                                     boolean setShopData,boolean setOrderBook){
        if(setUserData){
            cusUserBiz.setUserData(orderDetailsList,setUserData);
        }
        if(setShopData){
            orderDetailsList = this.setShopData(orderDetailsList,setShopData);
        }
        if(setOrderBook){
            orderDetailsList = this.setOrderBook(orderDetailsList,setOrderBook);
        }
        return orderDetailsList;
    }

    /**
     * 设置图书订单扩展数据
     * @param orderDetailsList 订单流水数据列表
     * @param setOrderBook
     * @return List<Order>
     */
    private List<OrderDetails> setOrderBook(List<OrderDetails> orderDetailsList, boolean setOrderBook){
        if(ObjectUtils.isNotEmpty(orderDetailsList) && setOrderBook){
            String orderIds = orderDetailsList.stream().map(e->e.getOrderId().toString()).distinct().collect(Collectors.joining(","));
            Map<BigDecimal,OrderBook> orderBookMap = orderBookBiz.findOrderBookByOrderIds(orderIds);
            if(ObjectUtils.isNotEmpty(orderBookMap)){
                orderDetailsList.forEach(e->{
                    OrderBook orderBook = orderBookMap.get(e.getOrderId());
                    e.setOrderBook(orderBook);
                });
            }
        }
        return orderDetailsList;
    }

    /**
     * 设置流水数据的商品信息
     * @param orderDetailsList 流水数据列表
     * @param setShopData 是否设置商品数据
     * @return List<OrderDetails>
     */
    private List<OrderDetails> setShopData(List<OrderDetails> orderDetailsList,boolean setShopData){
        if(ObjectUtils.isNotEmpty(orderDetailsList) && setShopData){
            List<ShopData> shopList = new ArrayList<>();
            orderDetailsList.forEach(e->{
                ShopData shop = new ShopData();
                shop.setShopId(e.getShopId());
                shop.setShopType(e.getShopType());
                shop.setDetailsId(e.getId());
                shopList.add(shop);
            });
            shopDataInit.setShopData(shopList);
            Map<BigDecimal,ShopData> shopMaps = shopList.stream().collect(Collectors.toMap(e->e.getDetailsId(), e->e));
            orderDetailsList.forEach(e->{
                ShopData shop = shopMaps.get(e.getId());
                e.setShop(shop);
            });
        }
        return orderDetailsList;
    }

    /**
     * 获取查询SQL
     * @param condition
     * @return
     */
    private String getWhereSql(OrderDetailsCondition condition){
        StringBuilder whereSql = new StringBuilder(" 1=1 ");
        if(ObjectUtils.isNotEmpty(condition)){
            if(DataUtil.idIsNotNull(condition.getId())){
                whereSql .append(" and id = ").append(condition.getId());
            }
            if(StringUtils.isNotEmpty(condition.getOrderIds())){
                whereSql .append(" and orderId in (").append(condition.getOrderIds()).append(")");
            }
            if(StringUtils.isNotEmpty(condition.getKeyword())){
                whereSql .append(this.getKeywordSql(condition.getKeyword(),condition.getUserIds()));
            }
            if(StringUtils.isNotEmpty(condition.getPayType())){
                whereSql .append(" and payType = '").append(condition.getPayType()).append("'");
            }
            if(StringUtils.isNotEmpty(condition.getNotPayType())){
                whereSql .append(" and payType not in (").append(condition.getNotPayType()).append(")");
            }
            if(StringUtils.isNotEmpty(condition.getPayTypeList())){
                whereSql .append(" and payType in (").append(condition.getPayTypeList()).append(")");
            }
            if(StringUtils.isNotEmpty(condition.getShopType())){
                whereSql .append(" and shopType = '").append(condition.getShopType()).append("'");
            }
            if(DataUtil.idIsNotNull(condition.getShopId())){
                whereSql .append(" and shopId = ").append(condition.getShopId());
            }
            if(StringUtils.isNotEmpty(condition.getShopName())){
                whereSql .append(" and shopName like '%").append(condition.getShopName().trim()).append("%'");
            }
            if(StringUtils.isNotEmpty(condition.getDetailStatus())){
                whereSql .append(" and detailStatus = '").append( condition.getDetailStatus()).append("'");
            }
            if(StringUtils.isNotEmpty(condition.getStatusList())){
                whereSql .append(" and detailStatus in (").append(condition.getStatusList()).append(")");
            }
            if(StringUtils.isNotEmpty(condition.getShareKey())){
                whereSql .append(" and shareKey = '").append( condition.getShareKey()).append("'");
            }
            if(DataUtil.idIsNotNull(condition.getUserId())){
                whereSql .append( " and userId=").append( condition.getUserId());
            }
            if(StringUtils.isNotEmpty(condition.getUserIds())){
                whereSql .append( "and userId in (").append(condition.getUserIds()).append(")");
            }
            if(ObjectUtils.isNotEmpty(condition.getBeginCreateTime())){
                whereSql .append(" and createTime >= '").append( DateUtils.format(condition.getBeginCreateTime(),"yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if(ObjectUtils.isNotEmpty(condition.getEndCreateTime())){
                whereSql .append(" and createTime <= '").append( DateUtils.format(condition.getEndCreateTime(),"yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if(ObjectUtils.isNotEmpty(condition.getBeginPayTime())){
                whereSql .append(" and payTime >= '").append( DateUtils.format(condition.getBeginPayTime(),"yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if(ObjectUtils.isNotEmpty(condition.getEndPayTime())){
                whereSql .append(" and payTime <= '").append( DateUtils.format(condition.getEndPayTime(),"yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if(ObjectUtils.isNotEmpty(condition.getBeginUpdateTime())){
                whereSql .append(" and updateTime >= '").append( DateUtils.format(condition.getBeginUpdateTime(),"yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if(ObjectUtils.isNotEmpty(condition.getEndUpdateTime())){
                whereSql .append(" and updateTime <= '").append( DateUtils.format(condition.getEndUpdateTime(),"yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if(ObjectUtils.isNotEmpty(condition.getGainDay())){
                whereSql .append(" and createTime >='").append(DateUtils.format(DateUtils.getPastDate(condition.getGainDay()==1?7:30) ,"yyyy-MM-dd")).append("'");
            }
        }
        whereSql.append(" order by updateTime desc");
        return whereSql.toString();
    }



    /**
     * 分页查询订单流水数据
     * @param condition 查询条件
     * @param setUserData 是否设置用户数据
     * @param setShopData 是否设置商品数据
     * @param setOrderBook 是否设置图书订单扩展数据
     * @param setOrder 是否设置订单扩展数据
     * @return PageInfo<OrderDetails>
     */
    public PageInfo<OrderDetails> findOrderDetailsSpecialPage(OrderDetailsCondition condition,
                                                       Pagination page, boolean setUserData, boolean setShopData,boolean setOrderBook,boolean setOrder){
        condition.setUserIds(this.getUsrIds(condition.getKeyword()));
        PageInfo<OrderDetails> orderDetailsPageInfo = this.findPage(this.getWhereSql(condition),page,null);
        this.setOrderDetailsExData(orderDetailsPageInfo.getList(),setUserData,setShopData,setOrderBook);
        //设置订单数据
        this.setOrder(orderDetailsPageInfo.getList(),setOrder);
        return orderDetailsPageInfo;
    }


    /**
     * 设置订单扩展数据
     * @param orderDetailsList 订单流水数据列表
     * @param setOrder
     * @return List<Order>
     */
    private List<OrderDetails> setOrder(List<OrderDetails> orderDetailsList, boolean setOrder){
        if(ObjectUtils.isNotEmpty(orderDetailsList) && setOrder){
            String orderIds = orderDetailsList.stream().map(e->e.getOrderId().toString()).distinct().collect(Collectors.joining(","));
            Map<BigDecimal,Order> orderMap = orderBiz.findOrderByOrderIds(orderIds);
            if(ObjectUtils.isNotEmpty(orderMap)){
                orderDetailsList.forEach(e->{
                    Order order = orderMap.get(e.getOrderId());
                    e.setOrder(order);
                });
            }
        }
        return orderDetailsList;
    }

    /**
     * 获取商品的下单量
     * @param params 查询条件
     * @return List<Map<String,Object>>
     */
    public List<Map<String,Object>> queryShopOrderNumList(Map<String,String> params){
        return orderDetailsDao.queryShopOrderNumList(OrderDetails.class,params);
    }

    /**
     * 查看交易分析统计中的交易数据
     * @param type 查询类型
     * @param timeSql 查询时间条件
     * @return List<TradePayOrderNum>
     */
    public List<TradePayOrderNum> tradePayOrderNumList(int type ,String timeSql){
        Map<String,Object> params = new HashMap<>();
        params.put("type",type);
        params.put("timeSql",timeSql);
        List<TradePayOrderNum> tradePayOrderNumList = orderDetailsDao.tradePayOrderNumList(OrderDetails.class,params);
        return tradePayOrderNumList;
    }

    //==========================以下是新代码，和当前业务无关===========================

    /**
     * 保存订单流水
     * @param order 订单对象
     * @param createOrderDataFrom 商品数据
     */
    public void saveOrderDetails(Order order, CreateOrderDataFrom createOrderDataFrom){
        List<ShopData> shopDataList = createOrderDataFrom.getShopList();
        List<OrderDetails> orderDetailsList = new ArrayList<>();
        shopDataList.forEach(shop->{
            OrderDetails orderDetails = this.getInitDetails(order);
            //设置商品数据
            this.setShopData(shop,orderDetails);
            orderDetailsList.add(orderDetails);
        });
        this.batchSave(orderDetailsList);
    }

    /**
     * 设置商品数据
     * @param shopData 商品对象
     * @param orderDetails 流水对象
     */
    private void setShopData(ShopData shopData, OrderDetails orderDetails){
        orderDetails.setShopId(shopData.getShopId());
        orderDetails.setShopType(shopData.getShopType());
        orderDetails.setShopName(shopData.getShopName());
        orderDetails.setBuyNum(shopData.getBuyNum());
        orderDetails.setPrice(shopData.getOldPrice());
        orderDetails.setMemberPrice(shopData.getMemberPrice());
        orderDetails.setYhPrice(shopData.getDiscountSubPrice());
        orderDetails.setActivityPrice(shopData.getActivitySubPrice());
        orderDetails.setRealPrice(shopData.getRealPrice());
        if(shopData.getShopType().equals(ShopType.ORDER_SHOP_COURSE)){
            orderDetails.setCourseType(shopData.getCourse().getCourseTypeKey());
            orderDetails.setValidType(shopData.getCourse().getValidType());
            orderDetails.setValidDay(shopData.getCourse().getValidDay());
            if (shopData.getCourse().getValidType()==2) {
                orderDetails.setValidTime(shopData.getCourse().getValidTime());
            }
        }
        if(shopData.getShopType().equals(ShopType.ORDER_SHOP_MEMBER)){
            orderDetails.setValidDay(shopData.getMember().getValidDay());
        }
        orderDetails.setShareKey(shopData.getShareKey());
    }

    /**
     * 获取初始流水记录对象
     * @param order 订单对象
     * @return OrderDetails
     */
    private OrderDetails getInitDetails(Order order){
        OrderDetails orderDetails = new OrderDetails();
        orderDetails.setOrderId(order.getId());
        orderDetails.setOrderNo(order.getOrderNo());
        orderDetails.setUserId(order.getUserId());
        if(order.getOrderStatus().equals(OrderStatus.SUCCESS)){
            orderDetails.setPayType(order.getPayType());
            orderDetails.setPayTime(order.getPayTime());
        }
        orderDetails.setDetailStatus(order.getOrderStatus());
        return orderDetails;
    }
}
